<!DOCTYPE html>
            
<HTML>
<HEAD>
<meta name="booktitle" content="Developing Applications With Objective Caml" >
 <meta charset="ISO-8859-1"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<META name="GENERATOR" content="hevea 1.05-7 of 2000-02-24">
<META NAME="Author" CONTENT="Christian.Queinnec@lip6.fr">
<LINK rel=stylesheet type="text/css" href="videoc-ocda.css">
<script language="JavaScript" src="videoc.js"><!--
//--></script>
<TITLE>
 The Module Language
</TITLE>
</HEAD>
<BODY class="regularBody">
<A HREF="book-ora130.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora132.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2> The Module Language</H2>The Objective CAML language features a sub-language for modules, which comes
in addition to the core language that we have seen so far. In this
module language, the interface of a module is called a
signature and its implementation is called a
structure. When there is no ambiguity, we will often use the
word ``module'' to refer to a structure.<BR>
<BR>
<A NAME="@fonctions373"></A>
<A NAME="@fonctions374"></A>
<A NAME="@fonctions375"></A>
<A NAME="@fonctions376"></A>
<A NAME="@fonctions377"></A>
<A NAME="@concepts283"></A>
<A NAME="@concepts284"></A>
<A NAME="@concepts285"></A><BR>
<BR>
The syntax for declaring signatures and structures is as follows:


<H3> Syntax </H3> <HR>


<TABLE CELLSPACING=2 CELLPADDING=0>
<TR><TD  ALIGN=left NOWRAP><B>module</B> <B>type</B> <I>NAME</I> <B>=</B></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>sig</B></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;<I>interface declarations</I></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>end</B></TD>
</TR></TABLE>



<HR>




<H3> Syntax </H3> <HR>


<TABLE CELLSPACING=2 CELLPADDING=0>
<TR><TD  ALIGN=left NOWRAP><B>module</B> <I>Name</I> <B>=</B></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>struct</B></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;&nbsp;&nbsp;<I>implementation definitions</I></TD>
</TR>
<TR><TD  ALIGN=left NOWRAP>&nbsp;&nbsp;<B>end</B></TD>
</TR></TABLE>



<HR>

<BR>
<BR>


<H3> Warning </H3> <HR>

The name of a module <EM>must</EM> start with an uppercase letter. There
are no such case restrictions on names of signatures, but by
convention we will use names in uppercase for signatures.


<HR>

<BR>
<BR>
Signatures and structures do not need to be bound to names: we can
also use anonymous signature and structure expressions, writing simply


<H3> Syntax </H3> <HR>


<B>sig</B> <I>declarations</I> <B>end</B>



<HR>




<H3> Syntax </H3> <HR>


<B>struct</B> <I>definitions</I> <B>end</B> 



<HR>


We write <I>signature</I> and <I>structure</I> to refer to either
names of signatures and structures, or anonymous signature and
structure expressions.<BR>
<BR>
Every structure possesses a default signature, computed by the type
inference system, which reveals all the definitions contained in the
structure, with their most general types. When defining a structure,
we can also indicate the desired signature by adding a signature constraint
(similar to the type constraints from the core language), using one of
the following two syntactic forms:
<A NAME="@concepts286"></A>
<A NAME="@concepts287"></A>


<H3> Syntax </H3> <HR>


<B>module</B> <I>Name</I> <B>:</B> <I>signature</I> <B>=</B>
<I>structure</I>



<HR>




<H3> Syntax </H3> <HR>


<B>module</B> <I>Name</I> <B>=</B>
<B>(</B><I>structure</I> <B>:</B> <I>signature</I><B>)</B>



<HR>


When an explicit signature is provided, the system checks that all the
components declared in the signature are defined in the structure
<I>structure</I>, and that the types are consistent. In other terms,
the system checks that the explicit signature provided is ``included
in'', or implied by, the default signature. If so, <I>Name</I> is
viewed in the remainder of the code with the signature
``<I>signature</I>'', and only the components declared in the signature
are accessible to the clients of the module. (This is the same behavior
we saw previously with interface files.)<BR>
<BR>
Access to the components of a module is via the dot notation:


<H3> Syntax </H3> <HR>


<I>Name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB><B>.</B><I>name</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB>



<HR>

<BR>
<BR>
We say that the name <I>name</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB> is qualified by the name
<I>Name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> of its defining module.<BR>
<BR>
The module name and the dot can be omitted using a directive to
open the module:


<H3> Syntax </H3> <HR>


 <B>open</B> <I>Name</I>



<HR>


In the scope of this directive, we can use short names <I>name</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB>
to refer to the components of the module <I>Name</I>. In case of name
conflicts, opening a module hides previously defined entities with the
same names, as in the case of identifier redefinitions.<BR>
<BR>
<A NAME="toc183"></A>
<H3> Two Stack Modules</H3><A NAME="mod-piles"></A>
We continue the example of stacks by recasting it in the module
language. The signature for a stack module is obtained by wrapping
the declarations from the <CODE>stack.mli</CODE> file in a signature
declaration:


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>STACK<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>exception</B><CODE> </CODE>Empty<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>create<CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>push<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>pop<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>clear<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>length<CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>iter<CODE>:</CODE><CODE> </CODE><TT>(</TT><I>'a</I><CODE> </CODE>-&gt;<CODE> </CODE>unit<TT>)</TT><CODE> </CODE>-&gt;<CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>module type STACK =</CODE><BR><CODE>  sig</CODE><BR><CODE>    type 'a t</CODE><BR><CODE>    exception Empty</CODE><BR><CODE>    val create : unit -&gt; 'a t</CODE><BR><CODE>    val push : 'a -&gt; 'a t -&gt; unit</CODE><BR><CODE>    val pop : 'a t -&gt; 'a</CODE><BR><CODE>    val clear : 'a t -&gt; unit</CODE><BR><CODE>    val length : 'a t -&gt; int</CODE><BR><CODE>    val iter : ('a -&gt; unit) -&gt; 'a t -&gt; unit</CODE><BR><CODE>  end</CODE><BR><BR>

</PRE>

A first implementation of stacks is obtained by reusing the <TT>Stack</TT> module from the standard library:


<PRE><BR># <B>module</B><CODE> </CODE>StandardStack<CODE> </CODE><CODE>=</CODE><CODE> </CODE>Stack<CODE> </CODE>;;<BR><CODE>module StandardStack :</CODE><BR><CODE>  sig</CODE><BR><CODE>    type 'a t = 'a Stack.t</CODE><BR><CODE>    exception Empty</CODE><BR><CODE>    val create : unit -&gt; 'a t</CODE><BR><CODE>    val push : 'a -&gt; 'a t -&gt; unit</CODE><BR><CODE>    val pop : 'a t -&gt; 'a</CODE><BR><CODE>    val clear : 'a t -&gt; unit</CODE><BR><CODE>    val length : 'a t -&gt; int</CODE><BR><CODE>    val iter : ('a -&gt; unit) -&gt; 'a t -&gt; unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
We then define an alternate implementation based on arrays:


<PRE><BR># <B>module</B><CODE> </CODE>MyStack<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>struct</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE><I>'a</I><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE><B>mutable</B><CODE> </CODE>sp<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int;<CODE> </CODE><B>mutable</B><CODE> </CODE>c<CODE> </CODE><CODE>:</CODE><CODE> </CODE><I>'a</I><CODE> </CODE>array<CODE> </CODE>}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>exception</B><CODE> </CODE>Empty<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>create<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>{<CODE> </CODE>sp<CODE>=</CODE><CODE>0</CODE><CODE> </CODE>;<CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE>[||]</CODE><CODE> </CODE>}<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>clear<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>0</CODE>;<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE><CODE>[||]</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>increase<CODE> </CODE>s<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>Array.append<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><TT>(</TT>Array.create<CODE> </CODE><CODE>5</CODE><CODE> </CODE>x<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>push<CODE> </CODE>x<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&gt;=</CODE><CODE> </CODE>Array.length<CODE> </CODE>s<CODE>.</CODE>c<CODE> </CODE><B>then</B><CODE> </CODE>increase<CODE> </CODE>s<CODE> </CODE>x;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT>s<CODE>.</CODE>sp<TT>)</TT><CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>x;<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>succ<CODE> </CODE>s<CODE>.</CODE>sp<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>pop<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>if</B><CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><CODE>=</CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE>raise<CODE> </CODE>Empty<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>else</B><CODE> </CODE><TT>(</TT>s<CODE>.</CODE>sp<CODE> </CODE><CODE>&lt;-</CODE><CODE> </CODE>pred<CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE>;<CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT>s<CODE>.</CODE>sp<TT>)</TT><TT>)</TT><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>length<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>s<CODE>.</CODE>sp<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>iter<CODE> </CODE>f<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>for</B><CODE> </CODE>i<CODE> </CODE><CODE>=</CODE><CODE> </CODE>pred<CODE> </CODE>s<CODE>.</CODE>sp<CODE> </CODE><B>downto</B><CODE> </CODE><CODE>0</CODE><CODE> </CODE><B>do</B><CODE> </CODE>f<CODE> </CODE>s<CODE>.</CODE>c<CODE>.</CODE><TT>(</TT>i<TT>)</TT><CODE> </CODE><B>done</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><CODE>module MyStack :</CODE><BR><CODE>  sig</CODE><BR><CODE>    type 'a t = { mutable sp: int; mutable c: 'a array }</CODE><BR><CODE>    exception Empty</CODE><BR><CODE>    val create : unit -&gt; 'a t</CODE><BR><CODE>    val clear : 'a t -&gt; unit</CODE><BR><CODE>    val increase : 'a t -&gt; 'a -&gt; unit</CODE><BR><CODE>    val push : 'a -&gt; 'a t -&gt; unit</CODE><BR><CODE>    val pop : 'a t -&gt; 'a</CODE><BR><CODE>    val length : 'a t -&gt; int</CODE><BR><CODE>    val iter : ('a -&gt; 'b) -&gt; 'a t -&gt; unit</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
These two modules implement the type <TT>t</TT> of stacks by different
data types.


<PRE><BR># StandardStack.create<CODE> </CODE>()<CODE> </CODE>;;<BR><CODE>- : '_a StandardStack.t = &lt;abstr&gt;</CODE><BR># MyStack.create<CODE> </CODE>()<CODE> </CODE>;;<BR><CODE>- : '_a MyStack.t = {MyStack.sp=0; MyStack.c=[||]}</CODE><BR>

</PRE>
<BR>
<BR>
To abstract over the type representation in <TT>Mystack</TT>, we add a
signature constraint by the <TT>STACK</TT> signature.


<PRE><BR># <B>module</B><CODE> </CODE>MyStack<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>MyStack<CODE> </CODE><CODE>:</CODE><CODE> </CODE>STACK<TT>)</TT><CODE> </CODE>;;<BR><CODE>module MyStack : STACK</CODE><BR># MyStack.create()<CODE> </CODE>;;<BR><CODE>- : '_a MyStack.t = &lt;abstr&gt;</CODE><BR>

</PRE>
<BR>
<BR>
The two modules <TT>StandardStack</TT> and <TT>MyStack</TT>
implement the same interface, that is, provide the same set of
operations over stacks, but their <TT>t</TT> types are different. It
is therefore impossible to apply operations from one module to values
from the other module:


<PRE><BR># <B>let</B><CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>StandardStack.create()<CODE> </CODE>;;<BR><CODE>val s : '_a StandardStack.t = &lt;abstr&gt;</CODE><BR># MyStack.push<CODE> </CODE><CODE>0</CODE><CODE> </CODE>s<CODE> </CODE>;;<BR><CODE>Characters 15-16:</CODE><BR><CODE>This expression has type 'a StandardStack.t = 'a Stack.t</CODE><BR><CODE>but is here used with type int MyStack.t</CODE><BR>

</PRE>
<BR>
<BR>
Even if both modules implemented the <I>t</I> type by the same
concrete type, constraining <TT>MyStack</TT> by the signature
<TT>STACK</TT> suffices to abstract over the <I>t</I> type,
rendering it incompatible with any other type in the system and
preventing sharing of values and operations between the various stack
modules.


<PRE><BR># <B>module</B><CODE> </CODE>S1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE>MyStack<CODE> </CODE><CODE>:</CODE><CODE> </CODE>STACK<CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>module S1 : STACK</CODE><BR># <B>module</B><CODE> </CODE>S2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE>MyStack<CODE> </CODE><CODE>:</CODE><CODE> </CODE>STACK<CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>module S2 : STACK</CODE><BR># <B>let</B><CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>S1.create<CODE> </CODE>()<CODE> </CODE>;;<BR><CODE>val s : '_a S1.t = &lt;abstr&gt;</CODE><BR># S2.push<CODE> </CODE><CODE>0</CODE><CODE> </CODE>s<CODE> </CODE>;;<BR><CODE>Characters 10-11:</CODE><BR><CODE>This expression has type 'a S1.t but is here used with type int S2.t</CODE><BR>

</PRE>
<BR>
<BR>
The Objective CAML system compares abstract types by names. Here, the two
types <TT>S1.t</TT> and <TT>S2.t</TT> are both abstract, and have
different names, hence they are considered as incompatible. It is
precisely this restriction that makes type abstraction effective, by
preventing any access to the definition of the type being abstracted.<BR>
<BR>
<A NAME="toc184"></A>
<H3> Modules and Information Hiding</H3>
This section shows additional examples of signature constraints hiding
or abstracting definitions of structure components.<BR>
<BR>

<H4> Hiding Type Implementations</H4>
Abstracting over a type ensures that the only way to construct values
of this type is via the functions exported from its definition
module. This can be used to restrict the values that can belong to
this type. In the following example, we implement an abstract type of
integers which, by construction, can never take the value 0.


<PRE>
<CODE> </CODE><BR># <B>module</B><CODE> </CODE>Int_Star<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>struct</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>int<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>exception</B><CODE> </CODE>Isnul<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>of_int<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>function</B><CODE> </CODE><CODE>0</CODE><CODE> </CODE>-&gt;<CODE> </CODE>raise<CODE> </CODE>Isnul<CODE> </CODE><CODE>|</CODE><CODE> </CODE>n<CODE> </CODE>-&gt;<CODE> </CODE>n<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>mult<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><CODE>*</CODE><CODE> </CODE><TT>)</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>:</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>exception</B><CODE> </CODE>Isnul<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>of_int<CODE> </CODE><CODE>:</CODE><CODE> </CODE>int<CODE> </CODE>-&gt;<CODE> </CODE>t<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>mult<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>t<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>module Int_Star :</CODE><BR><CODE>  sig type t exception Isnul val of_int : int -&gt; t val mult : t -&gt; t -&gt; t end</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Hiding Values</H4><A NAME="gensym-mod"></A>
We now define a symbol generator, similar to that of page
<A HREF="book-ora039.html#subsec-gensym">??</A>, using a signature constraint to hide the
state of the generator.<BR>
<BR>
We first define the signature <TT>GENSYM</TT> exporting only two
functions for generating symbols.


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>GENSYM<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>reset<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>next<CODE> </CODE><CODE>:</CODE><CODE> </CODE>string<CODE> </CODE>-&gt;<CODE> </CODE>string<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR>

</PRE>
<BR>
<BR>
We then implement this signature as follows:


<PRE><BR># <B>module</B><CODE> </CODE>Gensym<CODE> </CODE><CODE>:</CODE><CODE> </CODE>GENSYM<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>struct</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>c<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>reset<CODE> </CODE>()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>c<CODE>:=</CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>next<CODE> </CODE>s<CODE> </CODE><CODE>=</CODE><CODE> </CODE>incr<CODE> </CODE>c<CODE> </CODE>;<CODE> </CODE>s<CODE> </CODE><CODE>^</CODE><CODE> </CODE><TT>(</TT>string_of_int<CODE> </CODE><CODE>!</CODE>c<TT>)</TT><BR><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR><CODE>module Gensym : GENSYM</CODE><BR>

</PRE>
<BR>
<BR>
The reference <TT>c</TT> holding the state of the generator
<TT>Gensym</TT> is not accessible outside the two exported functions.


<PRE><BR># Gensym.reset();;<BR><CODE>- : unit = ()</CODE><BR># Gensym.next<CODE> </CODE><CODE>"T"</CODE>;;<BR><CODE>- : string = "T1"</CODE><BR># Gensym.next<CODE> </CODE><CODE>"X"</CODE>;;<BR><CODE>- : string = "X2"</CODE><BR># Gensym.reset();;<BR><CODE>- : unit = ()</CODE><BR># Gensym.next<CODE> </CODE><CODE>"U"</CODE>;;<BR><CODE>- : string = "U1"</CODE><BR># Gensym.c;;<BR><CODE>Characters 0-8:</CODE><BR><CODE>Unbound value Gensym.c</CODE><BR>

</PRE>
<BR>
<BR>
The definition of <TT>c</TT> is essentially local to the structure
<TT>Gensym</TT>, since it is hidden by the associated signature.
The signature constraint achieves more simply the same goal as the
local definition of a reference in the definition of the two functions
<TT>reset_s</TT> and <TT>new_s</TT> on page <A HREF="book-ora039.html#subsec-gensymloc">??</A>.<BR>
<BR>

<H4> Multiple Views of a Module</H4>
The module language and its signature constraints support taking
several views of a given structure. For instance, we can have a
``super-user interface'' for the module <TT>Gensym</TT>, allowing the
symbol counter to be reset, and a ``normal user interface'' that
permits only the generation of new symbols, but no other intervention
on the counter. To implement the latter interface, it suffices to
declare the signature:


<PRE><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>USER_GENSYM<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>next<CODE> </CODE><CODE>:</CODE><CODE> </CODE>string<CODE> </CODE>-&gt;<CODE> </CODE>string<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B>;;<BR><CODE>module type USER_GENSYM = sig val next : string -&gt; string end</CODE><BR>

</PRE>
<BR>
<BR>
We then implement it by a mere signature constraint.


<PRE><BR># <B>module</B><CODE> </CODE>UserGensym<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>Gensym<CODE> </CODE><CODE>:</CODE><CODE> </CODE>USER_GENSYM<TT>)</TT><CODE> </CODE>;;<BR><CODE>module UserGensym : USER_GENSYM</CODE><BR># UserGensym.next<CODE> </CODE><CODE>"U"</CODE><CODE> </CODE>;;<BR><CODE>- : string = "U2"</CODE><BR># UserGensym.reset()<CODE> </CODE>;;<BR><CODE>Characters 0-16:</CODE><BR><CODE>Unbound value UserGensym.reset</CODE><BR>

</PRE>
<BR>
<BR>
The <TT>UserGensym</TT> module fully reuses the code of the
<TT>Gensym</TT> module. In addition, both modules share the same counter:


<PRE><BR># Gensym.next<CODE> </CODE><CODE>"U"</CODE><CODE> </CODE>;;<BR><CODE>- : string = "U3"</CODE><BR># Gensym.reset()<CODE> </CODE>;;<BR><CODE>- : unit = ()</CODE><BR># UserGensym.next<CODE> </CODE><CODE>"V"</CODE><CODE> </CODE>;;<BR><CODE>- : string = "V1"</CODE><BR>

</PRE>
<BR>
<BR>
<A NAME="toc185"></A>
<H3> Type Sharing between Modules</H3>
As we saw on page <A HREF="book-ora131.html#mod-piles">??</A>, abstract types with different
names are incompatible. This can be problematic when we wish to share
an abstract type between several modules. There are two ways to
achieve this sharing: one is via a special sharing construct in the
module language; the other one uses the lexical scoping of modules.<BR>
<BR>

<H4> Sharing via Constraints</H4>
The following example illustrates the sharing issue. We define a
module <TT>M</TT> providing an abstract type <I>M.t</I>. We then
restrict <TT>M</TT> on two different signatures exporting different
subsets of operations. 


<PRE><BR># <B>module</B><CODE> </CODE>M<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><TT>(</TT><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>struct</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>int<CODE> </CODE>ref<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>create()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>add<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>incr<CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>get<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>if</B><CODE> </CODE><CODE>!</CODE>x<CODE>&gt;</CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE><TT>(</TT>decr<CODE> </CODE>x;<CODE> </CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><B>else</B><CODE> </CODE>failwith<CODE> </CODE><CODE>"Empty"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>:</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>create<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>add<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>get<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>int<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><BR><CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>S1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>create<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>add<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR><BR># <B>module</B><CODE> </CODE><B>type</B><CODE> </CODE>S2<CODE> </CODE><CODE>=</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>get<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>int<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE>;;<BR># <B>module</B><CODE> </CODE>M1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>M<CODE>:</CODE>S1<TT>)</TT><CODE> </CODE>;;<BR><CODE>module M1 : S1</CODE><BR># <B>module</B><CODE> </CODE>M2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>M<CODE>:</CODE>S2<TT>)</TT><CODE> </CODE>;;<BR><CODE>module M2 : S2</CODE><BR>

</PRE>
<BR>
<BR>
As written above, the types <I>M1.t</I> and <I>M2.t</I> are
incompatible. However, we would like to say that both types are
abstract but identical. To do this, Objective CAML offers special syntax to
declare a type equality over an abstract type in a signature.
<A NAME="@fonctions378"></A>
<A NAME="@concepts288"></A>
<A NAME="@concepts289"></A>


<H3> Syntax </H3> <HR>


<I>NAME</I> <B>with</B> 
 <B>type</B> <I>t</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> <B>=</B> <I>t</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB> 
 <B>and</B> ...


<HR>


This type constraint forces the type <I>t</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> declared in the
signature <I>NAME</I> to be equal to the type <I>t</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB>. <BR>
<BR>
Type constraints over all types exported by a sub-module can be declared
in one operation with the syntax


<H3> Syntax </H3> <HR>


<I>NAME</I> <B>with</B> <B>module</B> <I>Name</I><SUB><I><FONT SIZE=2>1</FONT></I></SUB> <B>=</B> <I>Name</I><SUB><I><FONT SIZE=2>2</FONT></I></SUB>



<HR>

<BR>
<BR>
Using these type sharing constraints, we can declare that the two
modules <TT>M1</TT> and <TT>M2</TT> define identical abstract types.


<PRE><BR># <B>module</B><CODE> </CODE>M1<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>M<CODE>:</CODE>S1<CODE> </CODE><B>with</B><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M.t<TT>)</TT><CODE> </CODE>;;<BR><CODE>module M1 : sig type t = M.t val create : unit -&gt; t val add : t -&gt; unit end</CODE><BR># <B>module</B><CODE> </CODE>M2<CODE> </CODE><CODE>=</CODE><CODE> </CODE><TT>(</TT>M<CODE>:</CODE>S2<CODE> </CODE><B>with</B><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M.t<TT>)</TT><CODE> </CODE>;;<BR><CODE>module M2 : sig type t = M.t val get : t -&gt; int end</CODE><BR># <B>let</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M1.create()<CODE> </CODE><B>in</B><CODE> </CODE>M1.add<CODE> </CODE>x<CODE> </CODE>;<CODE> </CODE><CODE> </CODE>M2.get<CODE> </CODE>x<CODE> </CODE>;;<BR><CODE>- : int = 1</CODE><BR>

</PRE>
<BR>
<BR>

<H4> Sharing and Nested Modules</H4>
<A NAME="@concepts290"></A>
Another possibility for ensuring type sharing is to use nested
modules. We define two sub-modules (<TT>M1</TT> et <TT>M2</TT>)
sharing an abstract type defined in the enclosing module <TT>M</TT>.


<PRE><BR># <B>module</B><CODE> </CODE>M<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><TT>(</TT><CODE> </CODE><B>struct</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<CODE> </CODE><CODE>=</CODE><CODE> </CODE>int<CODE> </CODE>ref<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>module</B><CODE> </CODE>M_hide<CODE> </CODE><CODE>=</CODE><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>struct</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>create()<CODE> </CODE><CODE>=</CODE><CODE> </CODE>ref<CODE> </CODE><CODE>0</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>add<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>incr<CODE> </CODE>x<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>let</B><CODE> </CODE>get<CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE><B>if</B><CODE> </CODE><CODE>!</CODE>x<CODE>&gt;</CODE><CODE>0</CODE><CODE> </CODE><B>then</B><CODE> </CODE><TT>(</TT>decr<CODE> </CODE>x;<CODE> </CODE><CODE>1</CODE><TT>)</TT><CODE> </CODE><B>else</B><CODE> </CODE>failwith<CODE> </CODE><CODE>"Empty"</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>module</B><CODE> </CODE>M1<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M_hide<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>module</B><CODE> </CODE>M2<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M_hide<CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE>:</CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>sig</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>type</B><CODE> </CODE>t<BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>module</B><CODE> </CODE>M1<CODE> </CODE><CODE>:</CODE><CODE> </CODE><B>sig</B><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>create<CODE> </CODE><CODE>:</CODE><CODE> </CODE>unit<CODE> </CODE>-&gt;<CODE> </CODE>t<CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>add<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>unit<CODE> </CODE><B>end</B><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>module</B><CODE> </CODE>M2<CODE> </CODE><CODE>:</CODE><CODE> </CODE><B>sig</B><CODE> </CODE><CODE> </CODE><B>val</B><CODE> </CODE>get<CODE> </CODE><CODE>:</CODE><CODE> </CODE>t<CODE> </CODE>-&gt;<CODE> </CODE>int<CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><BR><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><CODE> </CODE><B>end</B><CODE> </CODE><TT>)</TT><CODE> </CODE>;;<BR><CODE>module M :</CODE><BR><CODE>  sig</CODE><BR><CODE>    type t</CODE><BR><CODE>    module M1 : sig val create : unit -&gt; t val add : t -&gt; unit end</CODE><BR><CODE>    module M2 : sig val get : t -&gt; int end</CODE><BR><CODE>  end</CODE><BR>

</PRE>
<BR>
<BR>
As desired, values created by <TT>M1</TT> can be operated upon by
<TT>M2</TT>, while hiding the representation of these values.


<PRE><BR># <B>let</B><CODE> </CODE>x<CODE> </CODE><CODE>=</CODE><CODE> </CODE>M<CODE>.</CODE>M1.create()<CODE> </CODE>;;<BR><CODE>val x : M.t = &lt;abstr&gt;</CODE><BR># M<CODE>.</CODE>M1.add<CODE> </CODE>x<CODE> </CODE>;<CODE> </CODE>M<CODE>.</CODE>M2.get<CODE> </CODE>x<CODE> </CODE>;;<BR><CODE>- : int = 1</CODE><BR>

</PRE>

This solution is heavier than the previous solution based on type
sharing constraints: the functions from <TT>M1</TT> and <TT>M2</TT>
can only be accessed via the enclosing module <TT>M</TT>.<BR>
<BR>
<A NAME="toc186"></A>
<H3> Extending Simple Modules</H3>
Modules are closed entities, defined once and for all. In particular,
once an abstract type is defined using the module language, it is
impossible to add further operations on the abstract type that depend
on the type representation without modifying the module definition itself.
(Operations derived from existing operations can of course be added
later, outside the module.) As an extreme example,
if the module exports no creation function, clients of the module
will never be able to create values of the abstract type! <BR>
<BR>
Therefore, adding new operations that depend on the type
representation requires editing the sources of the module and adding
the desired operations in its signature and structure. Of course, we
then get a different module, and clients need to be recompiled.
However, if the modifications performed on the module signature did
not affect the components of the original signature, the remainder of
the program remains correct and does not need to be modified, just recompiled.<BR>
<BR>
<HR>
<A HREF="book-ora130.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="book-ora132.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
